<script setup>
import RelationGraph from 'relation-graph/vue3'

const props = defineProps({
  data: {
    type: Object,
    default: () => ({}),
  },
  fakeRoots: {
    type: Object,
    default: () => ({}),
  },
  ready: {
    type: Boolean,
    default: false,
  },
})

const graphWrapRef = ref(null)
const graphRef = ref(null)

const graphOptions = {
  backgroundImage: '',
  backgroundImageNoRepeat: true,
  disableZoom: false,
  disableDragNode: false,
  isMoveByParentNode: true,
  defaultFocusRootNode: true,
  disableNodeClickEffect: true,
  disableLineClickEffect: true,
  allowShowMiniToolBar: false,
  defaultNodeBorderWidth: 0,
  defaultNodeColor: '',
  defaultNodeBorderColor: '#409EFF',
  defaultLineColor: '#0173E7',
  defaultLineWidth: 3,
  defaultLineShape: 6,
  defaultNodeShape: 1,
  // defaultJunctionPoint: 'lr',
  defaultJunctionPoint: 'ltrb',
  disableDragCanvas: true,
  placeSingleNode: false,
  placeOtherGroup: false,
  moveToCenterWhenRefresh: false,
  zoomToFitWhenRefresh: false,
  defaultLineMarker: {
    markerWidth: '0',
    markerHeight: 20,
    refX: 3,
    refY: 3,
    data: 'M 0 0, V 6, L 4 3, Z',
  },
  layouts: [
    {
      label: '自定义',
      layoutName: 'fixed',
      layoutClassName: 'robot-relation-graph__wrap',
      from: 'left',
    },
  ],
}

const setGraphData = async () => {
  if(!Object.keys(props.data).length || !Object.keys(props.fakeRoots).length) {
    return
  }

  if(!graphRef.value?.$el || !graphWrapRef.value) {
    nextTick(() => {
      setGraphData()
    })
    return
  }

  const { width: containerRectWidth, height: containerRectHeight } = graphRef.value.$el.getBoundingClientRect()

  const _center = {
    x: 0,
    y: 0,
  }
  const nodeConfig = {
    width: 48,
    height: 48,
    subHeight: 28,
    padding: 4,
    lineSpaceX: 22,
    lineSpaceY: 24,
  }
  const graphData = {
    rootId: 'graph-root',
    nodes: [],
    lines: [],
  }
  const rootNode = {
    id: graphData.rootId,
    text: 'hidden-root',
    styleClass: 'r-graph-center',
    width: 2,
    height: 2,
    isHide: true,
    x: 1, // width / 2
    y: 1, // height / 2
  }

  graphData.nodes.push(rootNode)

  Object.keys(props.fakeRoots).forEach((key, i) => {
    const item = props.fakeRoots[key]
    const fakeRoot = {
      id: `root__${key}__${i}`,
      text: item.name,
      styleClass: 'r-graph__root',
      x: _center.x - item.offsetX * containerRectWidth,
      y: _center.y + item.offsetY * containerRectHeight - nodeConfig.height * 0.5,
      data: {
        type: 'root',
      },
    }
    graphData.nodes.push(fakeRoot)
    props.data[key] && props.data[key].forEach((text, j) => {
      const subNode = {
        id: `sub__${key}__${j}`,
        text,
        styleClass: `r-graph__sub ${item.offsetX < 0 ? 'r-graph__sub--left' : 'r-graph__sub--right'}`,
        width: 'auto',
        x: fakeRoot.x + nodeConfig.width * 0.8 + nodeConfig.lineSpaceX,
        y: fakeRoot.y + nodeConfig.height * 0.5 - nodeConfig.subHeight * 0.5 + (props.data[key].length > 1 ? (j - (props.data[key].length - 1) / 2) : item.offsetY > 0 ? 0.5 : -0.5) * (nodeConfig.subHeight + nodeConfig.lineSpaceY * 0.5),
        data: {
          type: 'sub',
        },
      }
      graphData.nodes.push(subNode)
      graphData.lines.push({
        from: fakeRoot.id,
        to: subNode.id,
        text: '',
        arrow: 'none',
        lineShape: 2,
      })
    })
  })

  const graphInstance = graphRef.value?.getInstance()
  if(graphInstance) {
    await graphInstance.setJsonData(graphData)
    nextTick(() => {
      graphInstance.refresh()
    })
  }
}

const isNoData = computed(() => props.ready && (!Object.keys(props.data).length || !Object.keys(props.fakeRoots).length))

watch(() => props.ready, (newReady) => {
  if(newReady) {
    setGraphData()
  }
}, { immediate: true })
</script>

<template>
  <section ref="graphWrapRef" class="robot-relation-graph">
    <RelationGraph ref="graphRef" :options="graphOptions">
      <template #node="{ node }">
        <div class="r-graph__custom-node">
          <div class="r-graph__node-wrap">
            <div class="r-graph__node-text">
              {{ node.text }}
            </div>
          </div>
        </div>
      </template>
      <template #line="{ line, link, relationGraph }">
        <GraphCustomLine
          v-if="line.isHide === false"
          :line="line"
          :link="link"
          :relation-graph="relationGraph"
        />
      </template>
    </RelationGraph>
    <UiEmpty v-show="isNoData.value" />
  </section>
</template>

<style lang='scss' scoped>
.robot-relation-graph {
  width: calc(100% - 1px);
  height: calc(100% - 1px);
  padding: 16px 0;

  :deep(.robot-relation-graph__wrap) {
    background-color: transparent;

    .r-graph__root .r-graph__custom-node {
      --r-border-radius: 45px;
      --r-border-width: 3px;
      --r-border-color: linear-gradient(48deg, #098AFF80, #017EFFCD 30%, #FFF 50%, #017EFFCD 70%, #098AFF80);

      position: relative;
      width: var(--r-border-radius);
      height: var(--r-border-radius);
      text-align: center;
      backdrop-filter: blur(10px);
      border-radius: var(--r-border-radius);

      &::before {
        /* 随便定义一个颜色 */
        --mask-bg: linear-gradient(red, red);
        --mask-clip: content-box, padding-box;

        position: absolute;
        top: calc(var(--r-border-width) * -1);
        left: calc(var(--r-border-width) * -1);
        width: 100%;
        height: 100%;
        padding: var(--r-border-width);
        content: "";
        background: var(--r-border-color);
        border-radius: var(--r-border-radius);
        mask-image: var(--mask-bg), var(--mask-bg);
        mask-clip: var(--mask-clip);

        /* 只显示下方遮罩，重合的地方不显示 */
        /* stylelint-disable-next-line property-no-vendor-prefix */
        -webkit-mask-composite: destination-out;

        /* exclude排除，只显示不重合的地方,Firefox支持4个属性 */
        mask-composite: exclude;
      }

      .r-graph__node-wrap {
        position: absolute;
        top: 3px;
        left: 3px;
        display: flex;
        align-items: center;
        justify-content: center;
        width: calc(100% - 6px);
        height: calc(100% - 6px);
        font-weight: 600;
        color: #000C2E;
        background: linear-gradient(180deg,#fff, #97d6ff 65%, #5ec0ff 87%, #8dd2ff 100%);
        border-radius: var(--r-border-radius);
      }
    }

    .r-graph__sub .r-graph__custom-node {
      --r-border-radius: 70px;
      --r-border-width: 2px;
      --r-border-color: linear-gradient(48deg, #008BFF1A, #008BFF33 20%, #FFF 50%, #008BFF33 80%, #008BFF1A);

      position: relative;
      width: max-content;
      max-width: 88px;
      background: linear-gradient(180deg,rgb(0 129 255 / 8%), rgb(0 93 255 / 20%) 100%);;
      backdrop-filter: blur(10px);
      border-radius: var(--r-border-radius);
      box-shadow: inset 0 0 7px 3px #008BFF1A;

      &::before {
        /* 随便定义一个颜色 */
        --mask-bg: linear-gradient(red, red);
        --mask-clip: content-box, padding-box;

        position: absolute;
        top: calc(var(--r-border-width) * -1);
        left: calc(var(--r-border-width) * -1);
        width: 100%;
        height: 100%;
        padding: var(--r-border-width);
        content: "";
        background: var(--r-border-color);
        border-radius: var(--r-border-radius);
        mask-image: var(--mask-bg), var(--mask-bg);
        mask-clip: var(--mask-clip);

        /* 只显示下方遮罩，重合的地方不显示 */
        /* stylelint-disable-next-line property-no-vendor-prefix */
        -webkit-mask-composite: destination-out;

        /* exclude排除，只显示不重合的地方,Firefox支持4个属性 */
        mask-composite: exclude;
      }

      .r-graph__node-text {
        padding: 2.5px 8px;
        font-size: 13px;
      }
    }
  }
}
</style>
